<?php

namespace Jobs\GeoLite2;

use Geo\City;
use Geo\Country;
use GeoLite2\Location;
use GeoLite2\Block;

class BlocksImportAction extends \Action {

	public $locations = [];
	public $locationTitles = [];
	
	protected function run() {
		$this->response->noRender ( true );
		$this->response->noCache ( true );
		$limit = 10000000;
		$i = 0;
		echo "\n";
		$sCity = $sNoCity = $sNoLoc = $sAll = $sNoIp4 = 0;

		$this->getLocations();
		
		$handle = fopen ( "GeoLite2-City-Blocks.csv", "r" );
		if ($handle) {
			while ( $limit -- && (($data = fgetcsv($handle, 8192 )) !== false) ) {
				if ($i++ > 0) {
					
					$sAll++;
					
					//network_start_ip,network_prefix_length,
					//geoname_id,registered_country_geoname_id,represented_country_geoname_id,
					//postal_code,latitude,longitude,is_anonymous_proxy,is_satellite_provider
					//::ffff:1.0.64.0,114,1861060,1861060,,,35.6900,139.6900,0,0
					if (preg_match('/^::ffff:((\d+)\.(\d+)\.(\d+)\.(\d+))$/', $data[0], $match)) {
						
						$ip = $match[2]*256*256*256 + $match[3]*256*256 + $match[4]*256 + $match[5];
						
						$toIp = (1 << (128 - $data[1])) - 1 + $ip;
						
						$location = $this->getLocationId($data[2]);
						$title = '';
						if (empty($location)) {
							$location = $this->getLocationId($data[3]);
						
							if (empty($location)) {
								$location = $this->getLocationId($data[4]);
							} else {
								$title = $this->locationTitles[$data[3]];
							}
							
						} else {
							$title = $this->locationTitles[$data[2]];
						}
						
						
						
						if (!empty($location)) {
							$entity = new Block();
							
							$entity->fromIp = $ip;
							$entity->toIp = $toIp;
							$entity->location[$location];
							
							$entity->save();
							if (substr($title, 0, 5) !== '*****') {
								$sCity++;
//								echo "#$i - ".$entity->fromIp." - ".$entity->toIp." - ".$title." - ok                  \n";
							} else {
								$sNoCity++;
//								echo "#$i - ".$entity->fromIp." - ".$entity->toIp." - ".$title." - no city                       \n";								
							}
						} else {
							$sNoLoc++;
//							echo "#$i - ".$data[0]." - skip - no location                                                       \n";
						}
						
						
					} else {
						$sNoIp4++;
//						echo "#$i - ".$data[0]." - skip                                                                    \n";
					}
					if ($i%100 == 0)  {						
						echo "\r#$sAll noIp4:$sNoIp4 noLoc:$sNoLoc noCity:$sNoCity Ok:$sCity (".$data[0].")  ";
						ob_flush();
					}
					
					// из-за проблем с перегревом на нюке - делаю паузы для остывания через каждый 100000 записей 
					//на две минуты
// 					if ($i%100000 == 0)  {
// 						sleep(60*5);
// 					}
				}
			}			
			fclose ( $handle );
		}
		echo "\r#$sAll noIp4:$sNoIp4 noLoc:$sNoLoc noCity:$sNoCity Ok:$sCity (".$data[0].")  ";
		echo "\n";
	}
	
	function getLocationId($geoname_id) {
		if (!isset($this->locations[$geoname_id])) {
			$location = Location::find()->where('geoname_id', intval($geoname_id))->active(false)->one();
			$this->locations[$geoname_id] = $location['_id'];
			$this->locationTitles[$geoname_id] = !empty($location['city_name'])?$location['city_name']:"*****".$location['country_name'];
		}
		return $this->locations[$geoname_id];
	}
	
	function getLocations() {
		$locations = Location::find()->active(false)->limit(1000000)->all();
		foreach ($locations as $loc) {
			$this->locations[intval($loc['geoname_id'])] = $loc['_id'];
			$this->locationTitles[intval($loc['geoname_id'])] = !empty($loc['city_name'])?$loc['city_name']:"*****".$loc['country_name'];
		}
		echo "locations:".count($this->locations)."\n";
	}
	
}
